/* 
 * File:   PsoModel.h
 * Author: jcrada
 *
 * Created on April 8, 2009, 7:57 PM
 */

#ifndef _PSOMODEL_H
#define	_PSOMODEL_H

#include "PsoParticle.h"
#include "RandomGsl.h"
#include "PsoOperators.h"

#include <QtXml/QDomDocument>
#include <QtXml/QDomElement>
namespace jcrada {

    class PsoSharingMethod;
    class PsoVelocityClampingMethod;
    class PsoInertiaUpdateMethod;

    class PsoModel {
    public:
        enum eSharingMethod {
            SM_NONE = -1, SM_RING, SM_STAR, SM_VON_NEUMANN
        };

        enum eInertiaMethod {
            IM_NONE = -1, IM_LINEAR, IM_NON_LINEAR
        };

        enum eVelocityMethod {
            VM_NONE = -1, VM_BASIC, VM_TANH
        };
    private:
        int _size;
        PsoParticle** _swarm;
        int _current_iteration;
        bool _lower_fitness_better;
        RandomGsl* _random_search;

        RandomGsl* _r1;
        RandomGsl* _r2;
        RandomGsl* _r3;

        double _nostalgia;
        double _envy;

        PsoSharingMethod* _sharing_method;
        PsoVelocityClampingMethod* _velocity_clamping_method;
        PsoInertiaUpdateMethod* _inertia_update_method;
    protected:

        

        virtual RandomGsl& getRandomSearch( ) const {
            return *this->_random_search;
        }
        virtual void updatePersonalPosition( PsoParticle& particle );
        virtual void updateVelocity( PsoParticle& particle );
        virtual void updatePosition( PsoParticle& particle );
    public:
        PsoModel( int size );
        PsoModel( int size, const PsoParticle& particle, bool lower_fitness_better = true );
        virtual ~PsoModel( );
        virtual void initialize( PsoParticle& particle );
        virtual void step( );

        virtual std::string toString( ) const;

        static PsoModel* fromXml( const QDomElement& xml, bool* ok );
        virtual void toXml( QDomDocument& xml, QDomElement* parent = NULL ) const;

        static int main( int argc, char** argv );

        virtual int getSize( ) const {
            return this->_size;
        }

        virtual void setParticle( int index, PsoParticle* particle ) {
            assert(index >= 0 && index < getSize());
            this->_swarm[index] = particle;
        }

        virtual PsoParticle& getParticle( int index ) const {
            assert(index >= 0 && index < getSize());
            return *this->_swarm[index];
        }

        virtual void setCurrentIteration( int iteration ) {
            this->_current_iteration = iteration;
        }

        virtual int getCurrentIteration( ) const {
            return this->_current_iteration;
        }

        virtual bool isLowerFitnessBetter( ) const {
            return this->_lower_fitness_better;
        }

        virtual void setLowerFitnessBetter( bool better ) {
            this->_lower_fitness_better = better;
        }

        virtual bool isBetter( double a, double b ) {
            return isLowerFitnessBetter() ? a < b : a > b;
        }

        virtual PsoSharingMethod* getSharingMethod( ) const {
            return this->_sharing_method;
        }

        virtual void setSharingMethod( PsoSharingMethod* method ) {
            this->_sharing_method = method;
        }

        virtual PsoVelocityClampingMethod* getVelocityClampingMethod( ) const {
            return this->_velocity_clamping_method;
        }

        virtual void setVelocityClampingMethod( PsoVelocityClampingMethod* method ) {
            this->_velocity_clamping_method = method;
        }

        virtual PsoInertiaUpdateMethod* getInertiaUpdateMethod( ) const {
            return this->_inertia_update_method;
        }

        virtual void setInertiaUpdateMethod( PsoInertiaUpdateMethod* method ) {
            this->_inertia_update_method = method;
        }

        virtual void setNostalgia( double nostalgia ) {
            this->_nostalgia = nostalgia;
        }

        virtual double getNostalgia( ) const {
            return this->_nostalgia;
        }

        virtual void setEnvy( double envy ) {
            this->_envy = envy;
        }

        virtual double getEnvy( ) const {
            return this->_envy;
        }

        virtual RandomGsl& getR1( ) const {
            return *this->_r1;
        }

        virtual RandomGsl& getR2( ) const {
            return *this->_r2;
        }

        virtual RandomGsl& getR3( ) const {
            return *this->_r3;
        }
    };
}

#endif	/* _PSOMODEL_H */

